package javax.per.toolkit.file;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.per.toolkit.security.DataEncryptor;
import javax.per.toolkit.security.DataEncryptor.PBEAlgorithmType;
import javax.per.toolkit.tools.Log;
import javax.per.toolkit.tools.Log.LogLevel;

public class FileUtil {

	public static void printFile(File f, String encoding) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(
				new FileInputStream(f), encoding));
		String tmp = null;
		while ((tmp = br.readLine()) != null) {
			System.out.println(tmp);
		}
		br.close();
	}

	public static void printFile(File f) throws IOException {
		FileInputStream br = new FileInputStream(f);
		int tmp = 0;
		while ((tmp = br.read()) != -1) {
			System.out.print(tmp + ",");
		}
		br.close();
	}

	public static void compareFile(File f1, File f2) {

	}

	public static void deleteFolder(String filePath) {
		File f = new File(filePath);
		deleteFolderLoop(f);
	}

	private static void deleteFolderLoop(File f) {
		if (f.isDirectory()) {
			for (File fi : f.listFiles()) {
				deleteFolderLoop(fi);
			}
			f.delete();
		} else {
			f.delete();
		}
	}

	public static void moveFolder(String srcDir, String desDir) {
		if (!new File(srcDir).exists())
			throw new Error("src file not found.");
		if (new File(desDir).exists())
			FileUtil.deleteFolder(desDir);
		new File(srcDir).renameTo(new File(desDir));
	}

	public static void splitFile(String file, int KByteSize, String desDir,
			String desName, boolean debug) throws IOException {
		if (debug)
			Log.setLevel(LogLevel.DEBUG);
		else
			Log.setLevel(LogLevel.OFF);
		InputStream is = new FileInputStream(file);
		int byteSize = KByteSize << 10;
		int readSum = 0;
		int readLen = 0;
		int fileCount = 1;
		byte[] b = new byte[2 << 10];
		File f = buildFile(desDir + File.separator + desName + fileCount);

		Log.getLogger().debug("Split: " + f.getAbsolutePath());
		OutputStream os = new FileOutputStream(f);
		while ((readLen = is.read(b)) != -1) {
			os.write(b, 0, readLen);
			readSum += readLen;
			if (readSum >= byteSize) {
				fileCount++;
				f = buildFile(desDir + File.separator + desName + fileCount);

				Log.getLogger().debug("Split: " + f.getAbsolutePath());
				os.close();
				os = new FileOutputStream(f);
				readSum = 0;
				readLen = 0;
			}
		}
		os.close();
		is.close();

		Log.getLogger().debug("Completion");
	}

	public static void encryptFile(String src, String des, String key)
			throws Exception {
		InputStream is = new FileInputStream(src);
		OutputStream os = new FileOutputStream(des);
		DataEncryptor.PBEEncrypt(is, os, key,
				PBEAlgorithmType.PBEWithMD5AndDES, new byte[] { 0, 0, 0, 0, 0,
						0, 0, 0 });
		is.close();
		os.close();
	}

	public static void decryptFile(String src, String des, String key)
			throws Exception {
		InputStream is = new FileInputStream(src);
		OutputStream os = new FileOutputStream(des);
		DataEncryptor.PBEDecrypt(is, os, key,
				PBEAlgorithmType.PBEWithMD5AndDES, new byte[] { 0, 0, 0, 0, 0,
						0, 0, 0 });
		is.close();
		os.close();
	}

	public static void changeEncoding(String filePath, String encoding)
			throws IOException {
		String content = FileUtil.getContent(filePath);
		OutputStream os = new FileOutputStream(filePath);
		os.write(content.getBytes(encoding));
		os.flush();
		os.close();
	}

	public static void mergeFile(String dirPath, String desPath,
			String nameStartWith, boolean debug) throws IOException {
		if (debug)
			Log.setLevel(LogLevel.DEBUG);
		else
			Log.setLevel(LogLevel.OFF);
		List<Integer> li = new ArrayList<Integer>();
		File fSrc = new File(dirPath);
		File[] fs = fSrc.listFiles();
		for (File f : fs) {
			li.add(Integer.parseInt(f.getName().replace(nameStartWith, "")));
		}
		Collections.sort(li);
		String pathStartWith = dirPath + File.separator + nameStartWith;
		File fDes = buildFile(desPath);
		OutputStream os = new FileOutputStream(fDes);
		for (int i : li) {
			InputStream is = new FileInputStream(pathStartWith + i);

			Log.getLogger().debug("Merge: " + (pathStartWith + i));
			byte[] bs = new byte[2 << 10];
			int len = 0;
			while ((len = is.read(bs)) != -1) {
				os.write(bs, 0, len);
			}
			is.close();
		}
		os.close();

		Log.getLogger().debug("Completion");
	}

	public static String getContent(String file) throws IOException {
		StringBuilder bui = new StringBuilder();
		String encoding = DetectEncoding.getEncoding(file);
		BufferedReader br = new BufferedReader(new InputStreamReader(
				new FileInputStream(file), encoding));
		char[] tmp = new char[1 << 10];
		int len = 0;
		while ((len = br.read(tmp)) != -1) {
			if (len < 1 << 10)
				tmp = Arrays.copyOfRange(tmp, 0, len);
			bui.append(tmp);
		}
		br.close();
		return bui.toString();
	}
	
	public static String getContent(String file,String encoding) throws IOException {
		StringBuilder bui = new StringBuilder();
		BufferedReader br = new BufferedReader(new InputStreamReader(
				new FileInputStream(file), encoding));
		char[] tmp = new char[1 << 10];
		int len = 0;
		while ((len = br.read(tmp)) != -1) {
			if (len < 1 << 10)
				tmp = Arrays.copyOfRange(tmp, 0, len);
			bui.append(tmp);
		}
		br.close();
		return bui.toString();
	}

	public static String getContent(URL url) throws IOException {
		StringBuilder bui = new StringBuilder();
		InputStream is = url.openStream();
		String encoding = DetectEncoding.getEncoding(is, is.available());
		BufferedReader br = new BufferedReader(new InputStreamReader(is,
				encoding));
		char[] tmp = new char[1 << 10];
		int len = 0;
		while ((len = br.read(tmp)) != -1) {
			if (len < 1 << 10)
				tmp = Arrays.copyOfRange(tmp, 0, len);
			bui.append(tmp);
		}
		br.close();
		return bui.toString();
	}

	public static BufferedReader getReader(String path)
			throws UnsupportedEncodingException, FileNotFoundException {
		String encoding = DetectEncoding.getEncoding(path);
		BufferedReader br = new BufferedReader(new InputStreamReader(
				new FileInputStream(path), encoding));
		return br;
	}

	public static BufferedWriter getWriter(String file) throws IOException {
		buildFile(new File(file).getAbsolutePath());
		String encoding = DetectEncoding.getEncoding(file);
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
				new FileOutputStream(file), encoding));
		return bw;
	}

	public static BufferedWriter getAppendWriter(String file)
			throws IOException {
		buildFile(new File(file).getAbsolutePath());
		String encoding = DetectEncoding.getEncoding(file);
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
				new FileOutputStream(file, true), encoding));
		return bw;
	}

	public static BufferedWriter getAppendWriter(String file,String encoding)
			throws IOException {
		buildFile(new File(file).getAbsolutePath());
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
				new FileOutputStream(file, true), encoding));
		return bw;
	}

	private static File buildFile(String filePath) throws IOException {
		File f = new File(filePath);
		if (!f.exists() || f.isDirectory()) {
			f.getParentFile().mkdirs();
			f.createNewFile();
		}
		return f;
	}

	public static String getExtension(String path) {
		String name = path;
		int index = name.lastIndexOf(".");
		if (index < 0 || index + 1 >= name.length()) {
			return "";
		} else {
			return name.substring(index + 1);
		}
	}

	public static String getFileName(String path) {
		String name = path;
		int index = name.lastIndexOf(".");
		if (index < 0 || index + 1 >= name.length()) {
			return name;
		} else {
			return name.substring(0, index);
		}
	}
}
